global dir_size

%define   SIZE_dir_entry          40
%define   SIZE_file_entry         48

%define   OFF_entry_type           0
%define   OFF_next_entry           8
%define   OFF_name                16

%define   OFF_DIR_first_entry     32

%define   OFF_FILE_attr           28
%define   OFF_FILE_size           32
%define   OFF_FILE_data           40

%define   TYPE_FILE 0
%define   TYPE_DIR  1

%define   NULL 0

section .text

; size_t dir_size(dir_entry *dir)

dir_size:
	mov     rdi, [rdi + OFF_DIR_first_entry]
	call    walker
	ret

walker:
	push rbx
	push r12

	xor  rbx, rbx
	mov  r12,rdi
	cmp  r12, NULL
	je   .end

	.loop:
		mov  rdx, [r12 + OFF_entry_type]
		cmp  byte dl, TYPE_FILE
		je   .isfile

			mov   rdi, [r12 + OFF_DIR_first_entry]
			call  walker
			add   rbx, rax
			jmp   .cont

		.isfile:
			add dword ebx, [r12 + OFF_FILE_size]

		.cont:
		mov  r12, [r12 + OFF_next_entry]
		cmp  r12, NULL
		jne  .loop

	.end:
	mov rax, rbx
	pop r12
	pop rbx
	ret
